﻿
namespace TransportAnalizer_2._0.ViewModels
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Windows.Input;
    using TransportAnalizer.HelpClasses;
    using Model;

    /// <summary>
    /// Main application view-model.
    /// </summary>
    public class NodeViewModel : ViewModel
    {
        private readonly INodeBusinessContext context;
        private Node selectedNode;
        private IBusinessContextFactory factory;

        /// <summary>
        /// Initializes a new instance of the <see cref="NodeViewModel"/> class.
        /// </summary>
        public NodeViewModel()
            : this(new BusinessContextFactory())
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="NodeViewModel"/> class.
        /// </summary>
        /// <param name="context">The existing <see cref="BusinessContextFactory"/> instnace the view-model will use.</param>
        public NodeViewModel(IBusinessContextFactory factory)
        {
            Nodes = new ObservableCollection<Node>();
            this.factory = factory;
            this.context = factory.GetNodeBusinessContext;
            NodeTypeViewModel = new NodeTypeViewModel(factory);
        }

        public NodeTypeViewModel NodeTypeViewModel
        {
            get;
            private set;//{ return new NodeTypeViewModel(factory); }

        }
        // TODO :Подумать нужна ли тут NodeTypeViewModel


        /// <summary>
        /// Gets a value indicating whether <see cref="SelectedNode"/> is not null.
        /// </summary>
        public bool CanModify
        {
            get
            {
                return SelectedNode != null;
            }
        }

        /// <summary>
        /// Gets the collection of node loaded from the data store.
        /// </summary>
        public ICollection<Node> Nodes
        {
            get;
            private set;
        }
 

        /// <summary>
        /// Gets or sets the current selected <see cref="Node"/>.
        /// </summary>
        public Node SelectedNode
        {
            get
            {
                return selectedNode;
            }
            set
            {
                selectedNode = value;
                NotifyPropertyChanged();
                // ReSharper disable once ExplicitCallerInfoArgument
                NotifyPropertyChanged("CanModify");
            }
        }

        /// <summary>
        /// Gets a value indicating whether the view model is valid.
        /// </summary>
        /// <remarks>
        /// You will notice that in this iteration of the demo project there isn't any actual validation happening. This
        /// is because the wiring into the CommandManager.RequerySuggested in ActionCommand was removed because it is not the
        /// proper way to do commanding. It has unexpected behavior and severe performance implications, and should never be
        /// done.
        /// 
        /// To enable this again, we will need to implement another view-model or use the facade pattern in place of using the
        /// customer entity directly so that we can implement INotifyPropertyChanged and execute ActionCommand.CanExecute(object)
        /// when necessary, ultimately updating the commanding system, which will re-enable the enabling/disabling of UI elements
        /// based on the return value.
        /// 
        /// This will be covered more in-depth in a later session.
        /// </remarks>
        public bool IsValid
        {
            get
            {
                return SelectedNode == null
                    ||
                     (
                       SelectedNode.Location!=null&&!SelectedNode.Location.IsEmpty
                     );
            }
        }

        /// <summary>
        /// Gets the command that invokes the retreival of a list of <see cref="Node"/> entities.
        /// </summary>
        public ICommand GetNodeListCommand
        {
            get
            {
                return new ActionCommand(p => GetNodeList());
            }
        }

        /// <summary>
        /// Gets the command that invokes the creation of a new <see cref="Node"/>.
        /// </summary>
        public ICommand AddCommand
        {
            get
            {
                return new ActionCommand(p => AddNode(),
                                         p => IsValid);
            }
        }

        /// <summary>
        /// Gets the command that invokes the deletion of the <see cref="SelectedNode"/>.
        /// </summary>
        public ICommand DeleteCommand
        {
            get
            {
                return new ActionCommand(p => DeleteNode());
            }
        }

        /// <summary>
        /// Gets the command that invokes an update of the <see cref="SelectedNode"/>.
        /// </summary>
        public ICommand UpdateCommand
        {
            get
            {
                return new ActionCommand(p => SaveNode(),
                                         p => IsValid);
            }
        }
        /// <summary>
        /// Open the NodeTypeView in new Window in a dialog mode.
        /// </summary>
        public ICommand OpenNodeTypeViewCommand
        {
            get 
            {
                return new ActionCommand(p => OpenNodeTypeView());
            }
        }

        private void OpenNodeTypeView()
        {
            Node PrevSelectedNode = SelectedNode;
            SelectedNode = null;
            var window = new Views.NodeTypeView
            {
                DataContext = NodeTypeViewModel
            };
            window.ShowDialog();
            SelectedNode = PrevSelectedNode;
        }

        private void GetNodeList()
        {
            Nodes.Clear();
            SelectedNode = null;

            foreach (var node in context.GetNodeList())
                Nodes.Add(node);
        }

        private void AddNode()
        {
                
                var node = new Node
                               {
                                   Location = System.Data.Entity.Spatial.DbGeography.FromText("POINT(82.9346000 55.0415000)"),
                               };

                try
                {
                    context.CreateNode(node);
                }
                catch (Exception ex)
                {
                    // TODO: In later session, cover error handling
                    return;
                }

                Nodes.Add(node);
            
        }

        private void SaveNode()
        {
            context.UpdateNode(SelectedNode);
        }

        private void DeleteNode()
        {
            context.DeleteNode(SelectedNode);
            Nodes.Remove(SelectedNode);
            SelectedNode = null;
        }
    }

}